﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcCms.Data;
using MvcCmsProjectTracker.ViewModels;
using System.IO;
using System.Web.Security;
using System.Web.Routing;
using MvcCms.Service.Cache;
using MvcCms.Service;
using MvcCmsProjectTracker.Service;

namespace MvcCmsProjectTracker.Controllers
{
    public class ProjectController : MvcCms.Service.Code.BaseClasses.CMSControllerBase
    {
        #region Constructors     
        private readonly ICacheService _cacheService;
        private readonly string _themeName;
        private readonly IAccountService _accountService;
        private readonly IBugService _bugService;
        private readonly IProjectService _projectService;
        public ProjectController(ICacheService cacheService, IAccountService accountService, IProjectService projectService, IBugService bugService, ICmsService cmsService, IZoneService zoneService)
            : base(cmsService, zoneService, accountService)
        {
            _cacheService = cacheService;
            _accountService = accountService;
            _bugService = bugService;
            _projectService = projectService;
            _themeName= _cacheService.GetCurrentPortal().Areas.Where(a => a.Name == "MvcCmsProjectTracker").FirstOrDefault().DefaultLayoutName;
        }
        #endregion
        
        // GET: /Project/
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Index()
        {
            var user = _accountService.GetUser();
            List<Project> projects = new List<Project>();

            if (User.IsInRole("Admin"))
                projects = _projectService.GetAllProjects().ToList();
            else
                projects = _projectService.GetMyProjects(user.UserID).ToList();
            ViewBag.Title = "Manage Projects";
            return View(projects);
        }

        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Create()
        {
            ViewBag.Title = "Create Project";
            return View();
        } 

        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Create(Project project)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var user = _accountService.GetUser();
                    project.CreatorName = user.UserName;
                    project.DateCreated = DateTime.Now;
                    project.LastUpdate = DateTime.Now;
                    project.Deleted = false;

                    _projectService.AddProject(project);
                    _projectService.Save();

                    ProjectMember newMember = new ProjectMember()
                    {
                        ProjectID = project.ProjectID,
                        UserID = user.UserID
                    };
                    _projectService.AddProjectMember(newMember);
                    _projectService.Save();

                    return RedirectToAction("Index");
                }
                catch
                {
                    return View();
                }
            }
            else
            {
                return View();
            }
        }
        
        // GET: /Project/Edit/5
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Edit(int id)
        {
            var viewModel = new ProjectEditViewModel();

            viewModel.Project = _projectService.GetProject(id);
            viewModel.ProjectMilestoneViewModel  = new ProjectMilestoneViewModel
            {
                ProjectID = id,
                Milestones = _projectService.GetProjectMilestones(id).ToList()
            };
            //Get Images            
            var milestoneImages = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Milestone")).GetFiles()
                                 select f.Name;
            foreach (string s in milestoneImages)
            {
                viewModel.ProjectMilestoneViewModel.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Milestone/" + s);
            }
            viewModel.ProjectCategoryViewModel = new ProjectCategoryViewModel()
            {
                ProjectID = id,
                Categories = _projectService.GetProjectCategories(id).ToList()
            };
            viewModel.ProjectPriorityViewModel = new ProjectPriorityViewModel()
            {
                ProjectID = id,
                Priorities = _projectService.GetProjectPriorities(id).ToList()
            };
            //Get Images
            var priorityImages = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Priority")).GetFiles()
                        select f.Name;
            foreach (string s in priorityImages)
            {
                viewModel.ProjectPriorityViewModel.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Priority/" + s);
            }
            viewModel.ProjectStatusViewModel = new ProjectStatusViewModel()
            {
                ProjectID = id,
                Statuses = _projectService.GetProjectStatuses(id).ToList()
            };
            //Get Images
            var statusImages = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Status")).GetFiles()
                        select f.Name;
            foreach (string s in statusImages)
            {
                viewModel.ProjectStatusViewModel.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Status/" + s);
            }

            viewModel.ProjectCustomFieldViewModel = new ProjectCustomFieldViewModel()
            {
                ProjectID = id,
                CustomFields = _projectService.GetProjectCustomFields(id).ToList()
            };

            viewModel.ProjectMemberViewModel = new ProjectMemberViewModel()
            {
                ProjectID = id,
                Members = _projectService.GetProjectMembers(id).ToList()
            };
            viewModel.ProjectMemberViewModel.AllUsers = _accountService.ListUsers4Ajax().OrderBy(u=>u.UserName).ToList();

            ViewBag.Title = "Edit Project";
            if (viewModel.Project != null)
                return View(viewModel);
            else
                return RedirectToAction("Index");
        }

        // POST: /Project/Edit/5
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Edit(int id, Project editedProject)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    Project project = _projectService.GetProject(id);
                    project.Name = editedProject.Name;
                    project.IsForHelpDesk = editedProject.IsForHelpDesk;
                    project.Description = editedProject.Description;
                    project.LastUpdate = DateTime.Now;

                    _projectService.Save();

                    return RedirectToAction("Index");
                }
                catch
                {
                    return View();
                }
            }
            else
            {
                return RedirectToAction("Edit", id);
            }
        }

        // GET: /Project/Delete/5
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Delete(int id)
        {
            Project project = _projectService.GetProject(id);

            if (project == null)
                return View("NotFound");

            return View(project);
        }

        // POST: /Project/Delete/5
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                Project project = _projectService.GetProject(id);
                _projectService.DeleteProject(project);
                _projectService.Save();
 
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        [Authorize]
        public ActionResult Profile()
        {
            var user = _accountService.GetUser();
            var results = new AccountProfileViewModel();

            results.UsersProjects = _projectService.GetMyProjects(user.UserID).ToList();
            results.Profile = _accountService.GetProfile(user.UserID);

            ViewBag.Title = "Edit My Profile";
            return View("Profile", "_HelpDesk", results);
        }

        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Settings()
        {
            var results = new SettingsViewModel();

            results._HelpPages = _projectService.GetHelpPages();

            ViewBag.Title = "Project Tracker Settings";
            return View(results);
        }
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Settings(int contentPageId, string rolesCanView)
        {
            var newHelpPage = new HelpPage
            {
                RolesCanView = rolesCanView,
                ContentPageID = contentPageId
            };
            _projectService.AddHelpPage(newHelpPage);
            _projectService.Save();

            var results = new SettingsViewModel();

            results._HelpPages = _projectService.GetHelpPages();

            ViewBag.Title = "Project Tracker Settings";
            return View(results);
        }
        [HttpPost]
        [Authorize]
        public ActionResult Profile(FormCollection collection)
        {
            var user = _accountService.GetUser();
            var profile = _accountService.GetProfile(user.UserID);

            profile.FirstName = collection["Profile.FirstName"];
            profile.LastName = collection["Profile.LastName"];
            if (collection["Profile.DefaultProjectID"] != null)
            {
                profile.DefaultProjectID = int.Parse(collection["Profile.DefaultProjectID"]);
            }
            _accountService.SetProfileData(profile);

            var results = new AccountProfileViewModel();
            results.UsersProjects = _projectService.GetMyProjects(user.UserID).ToList();
            results.Profile = profile;

            results.Message = "Profile Saved.";

            ViewBag.Title = "Edit My Profile";
            return View("Profile", "_HelpDesk", results);
        }

        // AJAX: /Project/DeleteMilestone/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeleteMilestone(int id)
        {
            ProjectMilestone milestone = _projectService.GetProjectMilestone(id);
            int projectID = milestone.ProjectID;

            _projectService.DeleteProjectMilestone(milestone);
            _projectService.Save();

            var results = new ProjectMilestoneViewModel
            {
                Message = Server.HtmlEncode(milestone.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Milestones = _projectService.GetProjectMilestones(projectID).ToList()
            };
            //Get Images
            var milestoneImages = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Milestone")).GetFiles()
                                  select f.Name;
            foreach (string s in milestoneImages)
            {
                results.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Milestone/" + s);
            }
            return PartialView("ProjectMilestones", results);
        }

        // AJAX: /Project/AddMilestone/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult AddMilestone(int id, FormCollection collection)
        {
            ProjectMilestone milestone = new ProjectMilestone();
            milestone.ProjectID = id;
            milestone.Name = Server.HtmlEncode(collection["milestonename"]);
            milestone.ImageUrl = collection["imageurl"];
            milestone.DateCreated = DateTime.Now;

            _projectService.AddProjectMilestone(milestone);
            _projectService.Save();

            var results = new ProjectMilestoneViewModel
            {
                Message = Server.HtmlEncode(milestone.Name) + " has been added to the project.",
                ProjectID = id,
                Milestones = _projectService.GetProjectMilestones(id).ToList()
            };
            //Get Images
            var milestoneImages = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Milestone")).GetFiles()
                                  select f.Name;
            foreach (string s in milestoneImages)
            {
                results.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Milestone/" + s);
            }
            return PartialView("ProjectMilestones", results);
        }

        // AJAX: /Project/DeleteCategory/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeleteCategory(int id)
        {
            ProjectCategory category = _projectService.GetProjectCategory(id);
            int projectID = category.ProjectID;

            //null any bugs with this category
            List<Bug> bugs = _bugService.GetBugsByCategory(projectID, id).ToList();
            foreach (Bug b in bugs)
            {
                //b.CategoryID = 0;
            }


            _projectService.DeleteProjectCategory(category);
            _projectService.Save();

            var results = new ProjectCategoryViewModel
            {
                Message = Server.HtmlEncode(category.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Categories = _projectService.GetProjectCategories(projectID).ToList()
            };
            return PartialView("ProjectCategories", results);
        }

        // AJAX: /Project/AddCategory/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult AddCategory(int id, FormCollection collection)
        {
            ProjectCategory category = new ProjectCategory();
            category.ProjectID = id;
            category.Name = Server.HtmlEncode(collection["categoryname"]);
            category.DateCreated = DateTime.Now;

            _projectService.AddProjectCategory(category);
            _projectService.Save();

            var results = new ProjectCategoryViewModel
            {
                Message = Server.HtmlEncode(category.Name) + " has been added to the project.",
                ProjectID = id,
                Categories = _projectService.GetProjectCategories(id).ToList()
            };
            return PartialView("ProjectCategories", results);
        }

        // AJAX: /Project/DeletePriority/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeletePriority(int id)
        {
            ProjectPriority priority = _projectService.GetProjectPriority(id);
            int projectID = priority.ProjectID;

            _projectService.DeleteProjectPriority(priority);
            _projectService.Save();

            var results = new ProjectPriorityViewModel
            {
                Message = Server.HtmlEncode(priority.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Priorities = _projectService.GetProjectPriorities(projectID).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Priority")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Priority/" + s);
            }
            return PartialView("ProjectPriorities", results);
        }

        // AJAX: /Project/AddPriority/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult AddPriority(int id, FormCollection collection)
        {
            ProjectPriority priority = new ProjectPriority();
            priority.ProjectID = id;
            priority.Name = Server.HtmlEncode(collection["priorityname"]);
            priority.ImageUrl = collection["imageurl"];
            priority.DateCreated = DateTime.Now;

            _projectService.AddProjectPriority(priority);
            _projectService.Save();

            var results = new ProjectPriorityViewModel
            {
                Message = Server.HtmlEncode(priority.Name) + " has been added to the project.",
                ProjectID = id,
                Priorities = _projectService.GetProjectPriorities(id).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Priority")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Priority/" + s);
            }

            return PartialView("ProjectPriorities", results);
        }

        // AJAX: /Project/DeleteStatus/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeleteStatus(int id)
        {
            ProjectStatus status = _projectService.GetProjectStatus(id);
            int projectID = status.ProjectID;

            _projectService.DeleteProjectStatus(status);
            _projectService.Save();

            var results = new ProjectStatusViewModel
            {
                Message = Server.HtmlEncode(status.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Statuses = _projectService.GetProjectStatuses(projectID).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Status")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Status/" + s);
            }
            return PartialView("ProjectStatuses", results);
        }

        // AJAX: /Project/AddStatus/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult AddStatus(int id, FormCollection collection)
        {
            ProjectStatus status = new ProjectStatus();
            status.ProjectID = id;
            status.Name = Server.HtmlEncode(collection["statusname"]);
            status.ImageUrl = collection["imageurl"];
            status.DateCreated = DateTime.Now;

            _projectService.AddProjectStatus(status);
            _projectService.Save();

            var results = new ProjectStatusViewModel
            {
                Message = Server.HtmlEncode(status.Name) + " has been added to the project.",
                ProjectID = id,
                Statuses = _projectService.GetProjectStatuses(id).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/RazorThemes/"+_themeName+"/Images/Status")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/RazorThemes/"+_themeName+"/Images/Status/" + s);
            }
            return PartialView("ProjectStatuses", results);
        }

        // AJAX: /Project/DeleteCustomField/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeleteCustomField(int id)
        {
            ProjectCustomField customField = _projectService.GetProjectCustomField(id);
            _projectService.DeleteProjectCustomField(customField);
            _projectService.Save();

            var results = new ProjectCustomFieldViewModel
            {
                Message = Server.HtmlEncode(customField.Name) + " has been added to the project.",
                ProjectID = customField.ProjectID,
                CustomFields = _projectService.GetProjectCustomFields(customField.ProjectID).ToList()
            };
            return PartialView("ProjectCustomFields", results);
        }

        // AJAX: /Project/AddCustomField/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult AddCustomField(int id, FormCollection collection)
        {
            ProjectCustomField customField = new ProjectCustomField();
            customField.ProjectID = id;
            customField.Name = Server.HtmlEncode(collection["fieldname"]);
            customField.Required = bool.Parse(collection["required"] ?? "false");
            customField.DataType = int.Parse(collection["datatype"]);
            customField.Deleted = false;

            _projectService.AddProjectCustomField(customField);
            _projectService.Save();

            var results = new ProjectCustomFieldViewModel
            {
                Message = Server.HtmlEncode(customField.Name) + " has been added to the project.",
                ProjectID = id,
                CustomFields = _projectService.GetProjectCustomFields(id).ToList()
            };

            return PartialView("ProjectCustomFields", results);
        }

        // AJAX: /Project/EditCustomField/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult EditCustomField(int id, FormCollection collection)
        {
            ProjectCustomField customField = _projectService.GetProjectCustomField(id);
            customField.Required = bool.Parse(collection["required"] ?? "false");
            _projectService.Save();

            var results = new ProjectCustomFieldViewModel
            {
                Message = Server.HtmlEncode(customField.Name) + " has been modified.",
                ProjectID = customField.ProjectID,
                CustomFields = _projectService.GetProjectCustomFields(customField.ProjectID).ToList()
            };
            return PartialView("ProjectCustomFields", results);
        }

        // AJAX: /Project/UpdateMembers/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult UpdateMembers(int id, FormCollection collection)
        {
            if (collection["add"] != null)
            {
                if (collection["nonmembers"] != null)
                {
                    List<string> users = collection["nonmembers"].Split(',').ToList();
                    foreach (string userId in users)
                    {
                        ProjectMember newMember = new ProjectMember()
                        {
                            ProjectID = id,
                            UserID = Guid.Parse(userId)
                        };
                        _projectService.AddProjectMember(newMember);
                    }
                    _projectService.Save();
                }
            }
            else
            {
                if (collection["members"] != null)
                {                
                    List<string> users = collection["members"].Split(',').ToList();
                    Project project = _projectService.GetProject(id);
                    foreach (string userId in users)
                    {
                        ProjectMember member = _projectService.GetProjectMember(id, Guid.Parse(userId));
                        //creator must be a member (for now)
                        if (member != null && member.User.UserName != project.CreatorName)
                        {
                            _projectService.DeleteProjectMember(member);
                        }
                    }
                    _projectService.Save();
                }
            }

            var results = new ProjectMemberViewModel()
            {
                ProjectID = id,
                Members = _projectService.GetProjectMembers(id).ToList()
            };
            results.AllUsers = _accountService.ListUsers4Ajax().OrderBy(u => u.UserName).ToList();

            return PartialView("ProjectMembers", results);
        }

        // AJAX: /Project/GetMilestoneURL/2
        [Authorize]
        public JsonResult GetMilestoneURL(int id)
        {
            string url = _projectService.GetProjectMilestone(id).ImageUrl;
            return Json(Url.Content(url));
        }

        // AJAX: /Project/GetPriorityURL/2
        [Authorize]
        public JsonResult GetPriorityURL(int id)
        {
            string url = _projectService.GetProjectPriority(id).ImageUrl;
            return Json(Url.Content(url));
        }

        // AJAX: /Project/GetStatusURL/2
        [Authorize]
        public JsonResult GetStatusURL(int id)
        {
            string url = _projectService.GetProjectStatus(id).ImageUrl;
            return Json(Url.Content(url));
        }

    }
}
